﻿//#define NEWLAT

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Markup;

using agree.configuration;

using alib;
using alib.Lattice;
using alib.Character;
using alib.Collections;
using alib.Debugging;
using alib.Enumerable;
using alib.Hashing;
using alib.dg;

namespace agree
{
#if NEWLAT
#if true
	public class newtrel<T> : rw_graph
		where T : class, ITfsSlot
	{
		static newtrel()
		{
			NoEdges = Collection<LatticeEdge>.None;
		}

		readonly public static new LatticeEdge[] NoEdges;

		public newtrel()
		{
			this._edges = new LatticeEdge[30];
		}

		LatticeEdge[] _edges;

		public new IEnumerable<LatticeEdge> Edges
		{
			get
			{
				var tmp = base.E;
				for (Eref er = Eref.Zero; er < EdgeAlloc; er++)
				{
					if (edge_is_valid(er))
					{
						var le = _edges[er];
						if (le == null || le.e != er)
							throw new Exception();
						yield return le;
					}
				}
			}
		}

		public LatticeVertex NewVertex()
		{
			return new LatticeVertex(this, add_vertex(0));
		}

		public LatticeEdge AddEdge(T data, LatticeVertex source = null, LatticeVertex target = null)
		{
			var vr_src = Vref.Zero;
			var vr_tgt = Vref.Zero;
			var er = base.create_edge(vr_src, vr_tgt, 0);
			return new LatticeEdge(this, data, er);
		}

		public bool IsAncestor(LatticeVertex v1, LatticeVertex v2)
		{
			if (v1 == v2)
				return true;
			if (v1.Level >= v2.Level)
				return false;
			return vertex_has_ancestor(v1.v, v2.v);
		}


		public abstract class LatticeItem
		{
			public LatticeItem(newtrel<T> trel)
			{
				this.trel = trel;
			}
			[DebuggerBrowsable(DebuggerBrowsableState.Never)]
			public readonly newtrel<T> trel;
		}

		[DebuggerDisplay("{ToString(),nq}")]
		public class LatticeVertex : LatticeItem
		{
			public LatticeVertex(newtrel<T> trel, Vref v)
				: base(trel)
			{
				this.v = v;
			}

			readonly public Vref v;

			public int Level { get { return trel.GetVertexLevels()[v]; } }

			public LatticeEdge[] lefts
			{
				get
				{
					throw not.impl;;
				}
			}

			public LatticeEdge[] rights
			{
				get
				{
					throw not.impl;;
				}
			}


			public IEnumerable<LatticeEdge> DescendantEdges()
			{
				var x = trel.vertex_descendants_and_self(v);
				throw not.impl;;
			}

			public IEnumerable<LatticeEdge> AnscestorEdges()
			{
				var x = trel.vertex_ancestors_and_self(v);
				throw not.impl;;
			}
		}

		[DebuggerDisplay("{LongDisplay,nq}")]
		public class LatticeEdge : LatticeItem
		{
			public LatticeEdge(newtrel<T> trel, T data, Eref e)
				: base(trel)
			{
				this.e = e;
				this.data = data;
			}
			readonly public Eref e;

			readonly public T data;

			public LatticeVertex Source
			{
				get
				{
					throw not.impl;;
				}
				set
				{
					throw not.impl; ;
				}
			}

			public LatticeVertex Target
			{
				get
				{
					throw not.impl;;
				}
				set
				{
					throw not.impl; ;
				}
			}

			public void Remove()
			{
				trel.delete_edge(e);
			}
		}
	}


	public class newlat<T> : newtrel<T>
		where T : class, ITfsSlot
	{
		public newlat()
		{
			this.StartVertex = NewVertex();
			this.EndVertex = NewVertex();
		}

		public LatticeVertex StartVertex;
		public LatticeVertex EndVertex;
	};

#else
	public class newlat<T> : ro_graph, IGraphData<T, AgreeTrellis<T>.LatticeVertex>, IEdata<T>,
		IIndexedHash<Lattice<T>.LatticeVertex>,
		IIndexedHash<T>
		where T : class, ITfsSlot
	{
		static ctor_args build_trell(AgreeTrellis<T> at)
		{
			ctor_args args;

			args.E = new Edge[0];
			args.V = new Vertex[0];

			//if (tfs is EmptyFeatureStructureTfs)
			//	args = default(ctor_args);
			//else
			//	new from_array_tfs_builder(tfs, e).go(tfs.c_act, e, out args);

			return args;
		}

		readonly AgreeTrellis<T> at;

		public newlat(AgreeTrellis<T> at)
			: base(build_trell(at))
		{
			this.at = at;
		}

		public T EdgeData(Eref e)
		{
			return default(T);
		}


		public Lattice<T>.LatticeVertex VertexData(Vref v) { return at.Vertices[(int)v]; }

		public IIndexedHash<Lattice<T>.LatticeVertex> VDict { get { return this; } }

		public IIndexedHash<T> EDict { get { return this; } }

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		///
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		int IIndexedHash<Lattice<T>.LatticeVertex>.this[Lattice<T>.LatticeVertex to_find]
		{
			get
			{
				throw not.impl;
			}
		}
		Lattice<T>.LatticeVertex IReadOnlyList<Lattice<T>.LatticeVertex>.this[int index]
		{
			get
			{
				throw not.impl;
			}
		}

		Lattice<T>.LatticeVertex[] IIndexedHash<Lattice<T>.LatticeVertex>.ConvertTo(IEnumerable<int> items)
		{
			throw not.impl;
		}

		int[] IIndexedHash<Lattice<T>.LatticeVertex>.ConvertFrom(IEnumerable<Lattice<T>.LatticeVertex> items)
		{
			throw not.impl;
		}

		int _IList<Lattice<T>.LatticeVertex>.Count { get { return at.VertexCount; } }
		int IReadOnlyCollection<Lattice<T>.LatticeVertex>.Count { get { return at.VertexCount; } }

		IEnumerator<Lattice<T>.LatticeVertex> IEnumerable<Lattice<T>.LatticeVertex>.GetEnumerator()
		{
			throw not.impl;
		}


		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		///
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


		int IIndexedHash<T>.this[T to_find]
		{
			get
			{
				throw not.impl;
			}
		}
		T IReadOnlyList<T>.this[int index]
		{
			get
			{
				throw not.impl;
			}
		}

		T[] IIndexedHash<T>.ConvertTo(IEnumerable<int> items)
		{
			throw not.impl;
		}

		int[] IIndexedHash<T>.ConvertFrom(IEnumerable<T> items)
		{
			throw not.impl;
		}

		int _IList<T>.Count { get { return at.EdgeCount; } }
		int IReadOnlyCollection<T>.Count { get { return at.EdgeCount; } }

		IEnumerator<T> IEnumerable<T>.GetEnumerator()
		{
			throw not.impl;
		}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		///
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		int System.Collections.ICollection.Count { get { throw not.valid; } }
		void System.Collections.ICollection.CopyTo(Array array, int index) { throw not.valid; }
		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw not.valid; }

		public bool IsSynchronized { get { return false; } }
		public Object SyncRoot { get { return this; } }
	};

#endif
#endif
}